package com.foo.designpattern.composite.safecomposite;

import junit.framework.TestCase;

/**
 * com.foo.designpattern.composite.safecomposite
 * Created with IntelliJ IDEA.
 * Created by jiang on 2016-05-20 16:22.
 *
 * @Description 测试类：合成模式(Composite)--安全式的合成模式
 * <p/>
 * 合成模式：合成模式属于对象的结构模式，有时又叫做“部分-整体”模式。
 * 合成模式将对象组织到树结构中，可以用来描述整体与部分的关系。合成模式可以使客户端将单纯元素与复杂元素同等看待。
 * 合成模式的实现根据所实现接口的区别分为两种形式，分别成为安全式和透明式。
 * <p/>
 * 安全式的合成模式要求管理聚集的方法只出现在树枝构件类中，而不出现在树叶构件类中。
 * 与安全式的合成模式不同的是，透明式的合成模式要求所有的具体构件类，不论树枝还是树叶结构，均符合一个固定接口。
 * <p/>
 * 合成模式把部分和整体的关系用树结构表示出来。
 * 比如，一个文件系统(Windows文件系统或者Linux文件系统)就是一个典型的合成模式系统。
 * 文件系统是一个树结构，树上长有树叶节点。树的节点有两种，一种是树枝节点，即目录，有内部树结构；另一种是文件，即树叶节点，没有内部树结构。
 * 显然，可以把目录和文件当做同一种对象同等对待和处理，这也就是合成模式的应用。
 * <p/>
 * 合成模式可以不提供父对象的管理方法，但是合成模式必须在合适的地方提供子对象的管理方法，诸如：add()、remove()以及getChild()等。
 * <p/>
 * 本例是安全式的合成模式
 * 安全式的合成模式是指：从客户端使用合成模式上看是否更安全，
 * 如果是安全的，那么就不会有发生误操作的可能，能访问的方法都是被支持的。
 * 另外，对于安全式的合成模式的实现，需要区分是树枝对象还是树叶对象。
 * 有时候，需要将对象进行类型转换，却发现类型信息丢失了，只好强行转换，这种类型转换必然是不够安全的。
 * <p/>
 * 安全式的合成模式涉及到三个角色：
 * 1、抽象构件(Component)角色：这是一个抽象角色，它给参加组合的对象定义出公共的接口及其默认行为，可以用来管理所有的子对象。
 * 合成对象通常把它所包含的字对象当做类型为Component的对象。
 * 在安全式的合成模式中，构件角色并不定义出管理子对象的方法，这一定义由树枝构件对象给出。
 * 2、树叶构件(Leaf)角色：树叶对象是没有下级子对象的对象，定义出参加组合的原始对象的行为。
 * 3、树枝构件(Composite)角色：代表参加组合的有下级子对象的对象。
 * 树枝构件类给出所有的管理子对象的方法，如add()、remove()以及getChild().
 */

public class SafeCompositeTestCase extends TestCase {
    public void testSafeComposite() {
        System.out.println("= = = = ↓↓↓安全式合成模式，测试开始↓↓↓ = = = =");

        /**
         * 树枝构件类(Composite)给出了addChild()、removeChild()以及getChild()等方法的声明和实现，
         * 而树叶构件类(Leaf)则没有给出这些方法的声明和实现，这样的做法是安全的做法。
         * 正因这个特点，客户端应用程序不可能错误的调用树叶构件的聚集方法，因为树叶构件没有这些方法，调用会导致编译错误。
         *
         * 安全式的合成模式的缺点是不够透明，因为树叶类和树枝类将具有不同的接口。
         */
        Composite root = new Composite("服装");
        Composite composite1 = new Composite("男装");
        Composite composite2 = new Composite("女装");

        Leaf leaf1 = new Leaf("衬衫");
        Leaf leaf2 = new Leaf("夹克");
        Leaf leaf3 = new Leaf("裙子");
        Leaf leaf4 = new Leaf("套装");

        root.addChild(composite1);
        root.addChild(composite2);
        composite1.addChild(leaf1);
        composite1.addChild(leaf2);
        composite2.addChild(leaf3);
        composite2.addChild(leaf4);

        root.printStructure("");

        System.out.println("= = = = ↑↑↑安全式合成模式，测试结束↑↑↑ = = = =");
    }
}
